﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Text;
using CMSLibrary.TagsCreate.CustomFunction;

namespace CMSLibrary.TagsCreate
{
    /// <summary>
    /// 模板替换引擎
    /// </summary>
    public partial class TemplateRepeater
    {

        public TemplateRepeater(string _sourceText, DataTable _sourceDT, int _currClassID)
        {
            sourceText = _sourceText;
            sourceDT = _sourceDT;
            currClassID = _currClassID;            
        }

        #region 变量
        private string sourceText = string.Empty;   //源文本        
        private DataTable sourceDT;  //源数据
        private string HeadHtml = string.Empty; //页头
        private string FootHtml = string.Empty; //页尾
        private StringBuilder RepeateText = new StringBuilder();    //重复文本
        private string[] parameters;    //外来参数
        private int repeatTimes = 0;    //自定义循环次数

        private const string Rep_LeftChar = "{Repeate}"; //重复左边符号
        private const string Rep_RightChar = "{/Repeate}"; //重复右边符号
        private const string Col_LeftChar = "(#"; //字段左边符号
        private const string Col_RightChar = "#)"; //字段右边符号
        private const string Fun_LeftChar_first = "[#"; //函数左边符号_优先
        private const string Fun_RightChar_first = "#]"; //函数右边符号_优先
        private const string Fun_LeftChar = "{#"; //函数左边符号
        private const string Fun_RightChar = "#}"; //函数右边符号
        private const string Para_LeftChar = "("; //参数左边符号
        private const string Para_RightChar = ")"; //参数右边符号
        private const string Para_Out_LeftChar = "/#Parameter[";    //外部参数_左
        private const string Para_Out_RightChar = "]#/";    //外部参数_右
        private const string Para_CurrentIndex = "/#Index#/";    //当前循环的索引

        private int currClassID = 0;    //当前栏目编号        
        #endregion

        #region 属性
        /// <summary>
        /// 自定义循环次数
        /// </summary>
        public int RepeatTimes
        {
            set { repeatTimes = value; }
        }
        /// <summary>
        /// 外来参数
        /// </summary>
        public string[] Parameters
        {
            set { parameters = value; }
        }
        /// <summary>
        /// 当前栏目编号
        /// </summary>
        public int CurrClassID
        {
            set { currClassID = value; }
        }
        /// <summary>
        /// 获取或设置源文本
        /// </summary>
        public string SourceText
        {
            set { sourceText = value; }
            get { return RepeateText.ToString(); }
        }
        /// <summary>
        /// 设置源数据行
        /// </summary>
        public DataTable SourceDT
        {
            set { sourceDT = value; }
        }
        #endregion

        #region 公开方法
        /// <summary>
        /// 替换开始
        /// </summary>
        public void ReplaceStart()
        {
            //替换外来参数
            SplitOutOfParameters();
            //拆分头和尾
            SplitHeadFoot();
            //先替换字段
            RepeateTable();
            //合并头尾
            if (RepeateText.ToString() != string.Empty)
            {
                RepeateText = new StringBuilder().Append(HeadHtml).Append(RepeateText).Append(FootHtml);
            }
            //先替换优先函数
            ReplaceCustomFunction(Fun_LeftChar_first, Fun_RightChar_first);
            //再替换函数
            ReplaceCustomFunction(Fun_LeftChar, Fun_RightChar);
            
        }

        /// <summary>
        /// 获取指定字符号间的文字
        /// </summary>
        /// <param name="source">文本源</param>
        /// <param name="leftChar">左边符号</param>
        /// <param name="rightChar">右边符号</param>
        /// <returns>符号间的字符串</returns>
        public static string SubText(string source, string leftChar, string rightChar)
        {
            //获取左边符号索引
            int leftIndex = source.IndexOf(leftChar);
            if (leftIndex != -1)
            {
                leftIndex += leftChar.Length;
                //获取紧接左边符号右边符号索引                
                int rightIndex = source.IndexOf(rightChar, leftIndex);
                if (rightIndex != -1)
                {
                    return source.Substring(leftIndex, rightIndex - leftIndex);
                }
            }
            return string.Empty;
        }
        #endregion

        #region 私有方法
        /// <summary>
        /// 替换外来参数
        /// </summary>
        private void SplitOutOfParameters()
        {
            if (parameters != null && parameters.Length != 0)
            {
                for (int i = 0; i < parameters.Length; i++)
                { 
                    //组合参数全称
                    string currpara = Para_Out_LeftChar + i.ToString() + Para_Out_RightChar;
                    sourceText = sourceText.Replace(currpara, parameters[i]);
                }
            }
        }
        /// <summary>
        /// 拆分头和尾
        /// </summary>
        private void SplitHeadFoot()
        {
            if (IsMatchObject(sourceText, Rep_LeftChar, Rep_RightChar))
            {
                //获取头部
                int headIndex = sourceText.IndexOf(Rep_LeftChar);
                HeadHtml = sourceText.Substring(0, headIndex);
                //获取尾部
                int footIndex = sourceText.LastIndexOf(Rep_RightChar) + Rep_RightChar.Length;
                FootHtml = sourceText.Substring(footIndex, sourceText.Length - footIndex);
                //获取重复区
                sourceText = SubText(sourceText, Rep_LeftChar, Rep_RightChar);
            }
        }
        /// <summary>
        /// 循环全部数据
        /// </summary>
        private void RepeateTable()
        {
            //表示有自定义循环
            if (repeatTimes != 0)
            {
                for (int i = 0; i < repeatTimes; i++)
                {                    
                    //替换当前索引
                    RepeateText.Append(RepeatIndex(sourceText,i));                    
                }
            }
            else
            {
                //如果数据源没有，则表示当前不是替换详细页
                if (sourceDT == null)
                {
                    RepeateText.Append(sourceText);
                    return;
                }

                //如果有数据源，但行数为0，则表示没查到数据，将模板内容清空，不让看到标签
                if (sourceDT.Rows.Count == 0)
                {
                    return;
                }

                for (int i = 0; i < sourceDT.Rows.Count; i++)
                {
                    DataRow dr = sourceDT.Rows[i];
                    string temp_source = ReplaceColumns(sourceText, dr);
                    RepeateText.Append(RepeatIndex(temp_source, i));    //替换当前索引
                }
            }
        }
        /// <summary>
        /// 替换当前索引
        /// </summary>
        /// <param name="source">源文本</param>
        /// <param name="currindex">当前索引</param>
        protected string RepeatIndex(string source, int currindex)
        {
            return source.Replace(Para_CurrentIndex, Convert.ToString(currindex + 1));
        }
        /// <summary>
        /// 替换字段文本
        /// </summary>
        private string ReplaceColumns(string source, DataRow sourceRow)
        {
            //直到没有匹配对象就不循环
            while (IsMatchObject(source, Col_LeftChar, Col_RightChar))
            {
                //获取字段文本
                string ColSource = SubText(source, Col_LeftChar, Col_RightChar);
                //将被字段替换的文本
                string MatchSource = Col_LeftChar + ColSource + Col_RightChar;
                //去空格
                ColSource = ColSource.Trim();
                //获取返回文本
                string result = string.Empty;
                if (sourceRow.Table.Columns.Contains(ColSource))
                {
                    result = (Convert.IsDBNull(sourceRow[ColSource])) ? string.Empty : Convert.ToString(sourceRow[ColSource]);
                }
                //替换该旧字段文本
                source = source.Replace(MatchSource, result);
            }

            return source;
        }
        /// <summary>
        /// 替换自定义函数
        /// </summary>
        private void ReplaceCustomFunction(string LeftChar, string RightChar)
        {
            //直到没有匹配对象就不循环
            while (IsMatchObject(RepeateText.ToString(), LeftChar, RightChar))
            {
                //获取函数文本
                string FunSource = SubText(RepeateText.ToString(), LeftChar, RightChar);
                //将被函数替换的文本
                string MatchSource = LeftChar + FunSource + RightChar;
                //获取方法名
                string FunName = GetFunctionName(FunSource);
                //获取参数文本
                string ParasText = GetParasOfFun(FunSource);
                //处理结果
                string result = string.Empty;
                //获取匹配的函数对象
                PFunctionBase fb = GetCustomFunction(FunName);
                //设置方法的参数
                if (fb != null)
                {
                    try
                    {
                        fb.CurrentClassID = currClassID;
                        fb.ParametersSource = ParasText;                        
                        //返回处理结果                    
                        result = fb.ToString();
                        fb.Dispose();
                    }
                    catch(Exception ex) { result = ex.Message; }
                }
                //替换该旧函数文本
                string tempText = RepeateText.Replace(MatchSource, result).ToString();
                RepeateText = new StringBuilder();
                RepeateText.Append(tempText);

            }

        }
        /// <summary>
        /// 是否有匹配对象
        /// </summary>
        /// <param name="source">源文本</param>
        /// <param name="leftChar">左符号</param>
        /// <param name="rightChar">右符号</param>
        /// <returns></returns>
        public static bool IsMatchObject(string source, string leftChar, string rightChar)
        {
            //获取左边符号索引
            int leftIndex = source.IndexOf(leftChar);
            if (leftIndex != -1)
            {
                leftIndex += leftChar.Length;
                //获取紧接左边符号右边符号索引                
                int rightIndex = source.IndexOf(rightChar, leftIndex);
                if (rightIndex != -1)
                {
                    return true;
                }
            }
            return false;
        }
        /// <summary>
        /// 返回方法名称
        /// </summary>
        /// <param name="FunNameParas">"Left(abc,2)"</param>
        /// <returns>"Left"</returns>
        private string GetFunctionName(string FunNameParas)
        {
            int leftindex = FunNameParas.IndexOf(Para_LeftChar);
            if (leftindex != -1)
            { return FunNameParas.Substring(0, leftindex).Trim(); }
            return string.Empty;
        }
        /// <summary>
        /// 返回方法的参数
        /// </summary>
        /// <param name="FunNameParas">"Left(abc,2)"</param>
        /// <returns>"abc,2"</returns>
        private string GetParasOfFun(string FunNameParas)
        {
            int leftindex = FunNameParas.IndexOf(Para_LeftChar);
            if (leftindex != -1)
            {
                leftindex += Para_LeftChar.Length;
                int rightindex = FunNameParas.LastIndexOf(Para_RightChar);
                if (rightindex != -1)
                {
                    return FunNameParas.Substring(leftindex, rightindex - leftindex).Trim();
                }
            }
            return string.Empty;
        }
        
        #endregion


    }
}